package jEDF.Montage;

import java.awt.*;
import java.awt.event.*;
import java.util.*;

import javax.swing.*;

import jEDF.Exceptions.*;
import jEDF.JEDF.*;

/**
 *
 * <p>Titre : jEDF</p>
 * <p>Description : Java European Data Format Viewer and Analyser</p>
 * <p>Author : Nizar Kerkeni</p>
 * <p>Copyright : Copyright (c) 2003-2006</p>
 * <p>Version 2.0</p>
 */

public class NewMontageDialog extends JDialog {

    private MontageToolbar montageToolbar = null;

    private Vector vectSignalPanels = new Vector();

    private JPanel mainPanel = new JPanel(new BorderLayout());
    private JPanel centerPanel = new JPanel();
    private JPanel upPanel = new JPanel();
    private JPanel downPanel = new JPanel();

    private JButton plusButton = new JButton("+");
    private JButton minusButton = new JButton("-");

    private JButton okButton = new JButton(JEDFMainWindow.getLocalizedString("OK"));
    private JButton cancelButton = new JButton(JEDFMainWindow.getLocalizedString("Cancel"));

    private JLabel jlAssignTo = new JLabel(JEDFMainWindow.getLocalizedString(
            "Assign this montage to "));
    private JButton jbM1 = new JButton("M1");
    private JButton jbM2 = new JButton("M2");
    private JButton jbM3 = new JButton("M3");
    private JButton jbM4 = new JButton("M4");

    private Montage currentMontage = null;

    private int numPanel = 1;

    private void showErrorDialog() {
        JOptionPane.showMessageDialog(this,
                                      JEDFMainWindow.getLocalizedString(
                                              JEDFMainWindow.
                                              getLocalizedString(
                "Please verify that you have selected a correct signal input for each channel.")),
                                      JEDFMainWindow.getLocalizedString(
                                              JEDFMainWindow.
                                              getLocalizedString("Error")),
                                      JOptionPane.ERROR_MESSAGE);
    }

    private void showErrorDialog(int numErrorPanel) {
        JOptionPane.showMessageDialog(this,
                                      JEDFMainWindow.getLocalizedString(
                                              "The signals of the channel n° ") +
                                      numErrorPanel +
                                      JEDFMainWindow.
                                      getLocalizedString(
                                              " do not correspond.\nPlease verify that they have the same sampling frequency."),
                                      JEDFMainWindow.getLocalizedString("Error"),
                                      JOptionPane.ERROR_MESSAGE);
    }

    /**
     * update the texts according to the current user selected langage
     */
    public void updateTexts() {
        cancelButton.setText(JEDFMainWindow.getLocalizedString("Cancel"));
        jlAssignTo.setText(JEDFMainWindow.getLocalizedString("Assign this montage to "));
        setTitle(JEDFMainWindow.getLocalizedString("Montage creation"));

    }

    /**
     * @param arg0 the parent frame
     * @param montageToolbar the corresponding montage toolbar
     */
    public NewMontageDialog(Frame arg0, MontageToolbar montageToolbar) {
        super(arg0, true);
        this.montageToolbar = montageToolbar;

        centerPanel.setLayout(new GridLayout(0, 1));
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        plusButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                addAPanel();
            }
        });

        minusButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                removeAPanel();
            }
        });
        okButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                try {
                    currentMontage = compileMontage();
                    dispose();
                }
                catch (IncorrectMontageException e) {
                    showErrorDialog();
                }
                catch (EDFSignalsNotCorrespondingException e) {
                    showErrorDialog(e.getNumSignal());
                }

            }
        });
        cancelButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                currentMontage = null;
                dispose();
            }
        });

        jbM1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                m1Selected();
                //dispose();
            }
        });
        jbM2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                //dispose();
                m2Selected();
            }
        });
        jbM3.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                //dispose();
                m3Selected();
            }
        });
        jbM4.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                //dispose();
                m4Selected();
            }
        });

        upPanel.add(plusButton);
        upPanel.add(minusButton);

        centerPanel.setBorder(BorderFactory.createEtchedBorder());

        mainPanel.add(upPanel, BorderLayout.NORTH);
        mainPanel.add(centerPanel, BorderLayout.CENTER);
        mainPanel.add(downPanel, BorderLayout.SOUTH);
        setContentPane(mainPanel);

        setTitle(JEDFMainWindow.getLocalizedString("Montage creation"));
        updateTexts();
    }

    private void m1Selected() {
        mSelected(0);
    }

    /**
     *
     * @param i 0..3
     */
    private void mSelected(int i) {
        try {
            montageToolbar.setMontage(compileMontage(), i);
            dispose();
        }
        catch (IncorrectMontageException e) {
            showErrorDialog();
        }
        catch (EDFSignalsNotCorrespondingException e) {
            showErrorDialog(e.getNumSignal());
        }

    }

    private void m2Selected() {
        mSelected(1);
    }

    private void m3Selected() {
        mSelected(2);
    }

    private void m4Selected() {
        mSelected(3);
    }


    private void addAPanel() {
        SignalPanel signalPanel = new SignalPanel(numPanel);
        numPanel++;
        vectSignalPanels.add(signalPanel);
        centerPanel.add(signalPanel);
        centerPanel.revalidate();
        pack();
    }

    private void removeAPanel() {
        if (vectSignalPanels.size() <= 1) {
            return;
        }

        numPanel--;
        SignalPanel signalPanel = (SignalPanel) vectSignalPanels.get(
                vectSignalPanels.size() - 1);
        vectSignalPanels.remove(vectSignalPanels.size() - 1);
        centerPanel.remove(signalPanel);
        centerPanel.revalidate();
        pack();
    }

    /**
     * @return display the dialog to create a new montage and return the result
     */
    public Montage getNewMontage() {
        clear();
        downPanel.add(okButton);
        downPanel.add(cancelButton);
        updateTexts();

        pack();

        setLocationRelativeTo(null);
        setVisible(true);
        return currentMontage; //compileMontage();
    }

    private void clear() {
        numPanel = 1;
        centerPanel.removeAll();
        downPanel.removeAll();
        vectSignalPanels.clear();
        addAPanel();
        setLocationRelativeTo(null);
    }

    private Montage compileMontage()
            throws IncorrectMontageException,
            EDFSignalsNotCorrespondingException {
        Montage montage = new Montage();

        Enumeration enu = vectSignalPanels.elements();
        while (enu.hasMoreElements()) {
            GraphProvider sp = (GraphProvider) enu.nextElement();
            JEDFGraph graph = sp.getGraph();
            if (graph == null) {
                montage = null;
                break;
            }
            montage.addGraph(graph);
        }

        if (montage == null) {
            throw new IncorrectMontageException();
        }

        return montage;
    }

    /**
     * display the dialog to assign a new montage to quick shortcut buttons
     * (M1..M4)
     */
    public void assignNewMontage() {
        clear();
        downPanel.add(jlAssignTo);
        downPanel.add(jbM1);
        downPanel.add(jbM2);
        downPanel.add(jbM3);
        downPanel.add(jbM4);
        downPanel.add(cancelButton);
        updateTexts();
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }

    private interface GraphProvider {
        /**
         * @return a graph
         * @throws EDFSignalsNotCorrespondingException if the two signals don't match
         */
        public JEDFGraph getGraph()
                throws EDFSignalsNotCorrespondingException;
    }


    private class SignalPanel extends JPanel implements GraphProvider {
        private String noneString = JEDFMainWindow.getLocalizedString("None");

        private final String UNIPOLAR = JEDFMainWindow.getLocalizedString("Unipolar");
        private final String BIPOLAR = JEDFMainWindow.getLocalizedString("Bipolar");

        private JRadioButton jrbUnipolar = new JRadioButton(JEDFMainWindow.
                getLocalizedString("Unipolar"));
        private JRadioButton jrbBipolar = new JRadioButton(JEDFMainWindow.
                getLocalizedString("Bipolar"));
        private ButtonGroup buttonGroup = new ButtonGroup();

        private JPanel jpSignal = new JPanel(new CardLayout());

        private UnipolarPanel unipolarPanel = new UnipolarPanel();
        private BipolarPanel bipolarPanel = new BipolarPanel();

        private int numPanel = 0;

        /**
         * @param numPanel the number of the signal in this dialog
         */
        public SignalPanel(int numPanel) {
            this.numPanel = numPanel;
            setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));

            buttonGroup.add(jrbBipolar);
            buttonGroup.add(jrbUnipolar);

            jrbBipolar.setSelected(true);

            jrbBipolar.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent arg0) {
                    if (jrbBipolar.isSelected()) {
                        displayPanel(BIPOLAR);
                    }
                }
            });

            jrbUnipolar.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent arg0) {
                    if (jrbUnipolar.isSelected()) {
                        displayPanel(UNIPOLAR);
                    }
                }
            });

            jpSignal.add(bipolarPanel, BIPOLAR);
            jpSignal.add(unipolarPanel, UNIPOLAR);

            JPanel jpTemp = new JPanel();
            jpTemp.add(jrbBipolar);
            jpTemp.add(jrbUnipolar);

            add(new JLabel(numPanel + ")   "));
            add(jpTemp);
            add(jpSignal);
        }

        private void displayPanel(String panelName) {
            CardLayout cl = (CardLayout) (jpSignal.getLayout());
            cl.show(jpSignal, panelName);
        }


        private class JCBSignalChoice extends JComboBox {
            /**
             * constructor : create a custom JComboBox to choose a signal from
             */
            public JCBSignalChoice() {
                super();
                addItem(noneString);

                Montage defaultMontage = Montage.getDefaultMontage();
                String[] signalNames = defaultMontage.listAllSignalName();

                for (int i = 0; i < signalNames.length; i++) {
                    addItem(signalNames[i]);
                }

                setSelectedItem(noneString);
            }
        }


        private class UnipolarPanel extends JPanel implements GraphProvider {
            private JCBSignalChoice jcbSignalChoice = new JCBSignalChoice();

            /**
             * constructor of a panel to choose an unipolar signal
             */
            public UnipolarPanel() {
                add(jcbSignalChoice);
                pack();
            }

            /* (non-Javadoc)
             * @see NewMontageDialog.SignalProvider#getSignal()
             */
            public JEDFGraph getGraph() {
                String userChoice = (String) jcbSignalChoice.getSelectedItem();
                if (userChoice.compareToIgnoreCase(noneString) == 0) {
                    return null;
                }
                return Montage.getDefaultMontage().getGraph(userChoice);
            }
        }


        private class BipolarPanel extends JPanel implements GraphProvider {
            private JCBSignalChoice choice1 = new JCBSignalChoice();
            private JCBSignalChoice choice2 = new JCBSignalChoice();
            private JLabel jlMinus = new JLabel("<html><b> - </b></html>");

            /**
             * constructor of a panel to create a bipolar signal
             */
            public BipolarPanel() {
                add(choice1);
                add(jlMinus);
                add(choice2);
                pack();
            }


            /* (non-Javadoc)
             * @see NewMontageDialog.GraphProvider#getGraph()
             */
            public JEDFGraph getGraph()
                    throws EDFSignalsNotCorrespondingException {
                String userChoice1 = (String) choice1.getSelectedItem();
                String userChoice2 = (String) choice2.getSelectedItem();

                if (userChoice1.compareToIgnoreCase(noneString) == 0
                    || userChoice2.compareToIgnoreCase(noneString) == 0) {
                    return null;
                }

                JEDFGraph graph1 = Montage.getDefaultMontage().getGraph(userChoice1);
                JEDFGraph graph2 = Montage.getDefaultMontage().getGraph(userChoice2);

                if (graph1 == null || graph2 == null) {
                    return null;
                }

                return new JEDFGraph(graph1, graph2);

            }
        }


        /* (non-Javadoc)
         * @see NewMontageDialog.SignalProvider#getSignal()
         */
        public JEDFGraph getGraph() throws EDFSignalsNotCorrespondingException {
            if (jrbUnipolar.isSelected()) {
                return ((GraphProvider) unipolarPanel).getGraph();
            }
            try {
                return ((GraphProvider) bipolarPanel).getGraph();
            }
            catch (EDFSignalsNotCorrespondingException snce) {
                snce.setNumSignal(numPanel);
                throw snce;
            }
        }
    }


}
